
#include <string.h>
#include <stdio.h>
#include "../Main.h"
#include "Occult.h"
#include "../astro/Astrology.h"
#include "../tarot/Tarot.h"


const int Occult::char2symbol[256] = {
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,						0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,						0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, SYMBOL_PLUTO,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,						0, 0, 0, 0,

	0,						SYMBOL_AIR,			SYMBOL_MERCURY,		SYMBOL_CANCER,			// " ABC"
	SYMBOL_VENUS,		SYMBOL_CAPRICORN,	SYMBOL_SATURN,			SYMBOL_MOON,			// "DEFG"
	SYMBOL_ARIES,		SYMBOL_VIRGO,		SYMBOL_FIRE,			SYMBOL_JUPITER,		// "HIJK"
	SYMBOL_LIBRA,		SYMBOL_WATER,		SYMBOL_SCORPIO,		SYMBOL_EARTH,			// "LMNO"

	SYMBOL_MARS,		SYMBOL_PISCES,		SYMBOL_SUN,				SYMBOL_SAGITTARIUS,	// "PQRS"
	SYMBOL_LEO,			SYMBOL_SPIRIT,		SYMBOL_TAURUS,			SYMBOL_NEPTUNE,		// "TUVW"
	SYMBOL_AQUARIUS,	SYMBOL_URANUS,		SYMBOL_GEMINI,			0,							// "XYZ "
	0, 0, 0, 0,

	0,						SYMBOL_AIR,			SYMBOL_MERCURY,		SYMBOL_CANCER,			// " abc"
	SYMBOL_VENUS,		SYMBOL_CAPRICORN,	SYMBOL_SATURN,			SYMBOL_MOON,			// "defg"
	SYMBOL_ARIES,		SYMBOL_VIRGO,		SYMBOL_FIRE,			SYMBOL_JUPITER,		// "hijk"
	SYMBOL_LIBRA,		SYMBOL_WATER,		SYMBOL_SCORPIO,		SYMBOL_EARTH,			// "lmno"

	SYMBOL_MARS,		SYMBOL_PISCES,		SYMBOL_SUN,				SYMBOL_SAGITTARIUS,	// "pqrs"
	SYMBOL_LEO,			SYMBOL_SPIRIT,		SYMBOL_TAURUS,			SYMBOL_NEPTUNE,		// "tuvw"
	SYMBOL_AQUARIUS,	SYMBOL_URANUS,		SYMBOL_GEMINI,			0,							// "xyz "
	0, 0, 0, 0,

	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,

	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
	0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,		0, 0, 0, 0,
};

const char Occult::symbol2char[256] = "UJAMOHVZCTILNSEXQRGBDPKFYW+";
const int Occult::symbol2element[256] = {
	SYMBOL_SPIRIT,	SYMBOL_FIRE,	SYMBOL_AIR,		SYMBOL_WATER,	SYMBOL_EARTH,

	SYMBOL_FIRE,	SYMBOL_EARTH,	SYMBOL_AIR,		SYMBOL_WATER,
	SYMBOL_FIRE,	SYMBOL_EARTH,	SYMBOL_AIR,		SYMBOL_WATER,
	SYMBOL_FIRE,	SYMBOL_EARTH,	SYMBOL_AIR,		SYMBOL_WATER,

	SYMBOL_FIRE,	SYMBOL_WATER,	SYMBOL_AIR,		SYMBOL_EARTH,	SYMBOL_FIRE,
	SYMBOL_FIRE,	SYMBOL_EARTH,	SYMBOL_AIR,		SYMBOL_WATER,	SYMBOL_WATER,
};

const char Occult::elemConv[256] = {
	// OCCULT_SYMBOL: SYMBOL_SPIRIT=0,SYMBOL_FIRE=1,SYMBOL_AIR=2,SYMBOL_WATER=3,SYMBOL_EARTH=4
	'u','j','a','m','o',0,0,0,
	0,0,0,0,0,0,0,0,
	// OCCULT_ASTRO: ASTRO_FIRE=1,ASTRO_EARTH=2,ASTRO_AIR=3,ASTRO_WATER=4,ASTRO_SPIRIT=5
	0,SYMBOL_FIRE,SYMBOL_EARTH,SYMBOL_AIR,SYMBOL_WATER,SYMBOL_SPIRIT,0,0,
	0,ASTRO_FIRE,ASTRO_AIR,ASTRO_WATER,ASTRO_EARTH,0,0,0,
	// OCCULT_QABALAH
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	// OCCULT_TAROT: TAROT_FIRE=0,TAROT_WATER=1,TAROT_AIR=2,TAROT_EARTH=3,TAROT_SPIRIT=4
	SYMBOL_FIRE,SYMBOL_WATER,SYMBOL_AIR,SYMBOL_EARTH,SYMBOL_SPIRIT,0,0,0,
	0,TAROT_FIRE,TAROT_EARTH,TAROT_AIR,TAROT_WATER,TAROT_SPIRIT,0,0,
	// OCCULT_ENOCH
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	// OCCULT_ALCHEMY
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
	// OCCULT_WICCA
	0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,
};


symbol_t Occult::singleCode(int s,int c,symbol_t c1) {
	return (c1<<16)|((s&0x3f)<<10)|(c&0xff);
}
symbol_t Occult::doubleCode(int s,int c,symbol_t c1,symbol_t c2) {
	return ((((c1&0xffffff)<<24)|(c2&0xffffff))<<16)|((s&0x3f)<<10)|(1<<8)|(c&0xff);
}
symbol_t Occult::tripleCode(int s,int c,symbol_t c1,symbol_t c2,symbol_t c3) {
	return ((((c1&0xffff)<<32)|((c2&0xffff)<<16)|(c3&0xffff))<<16)|((s&0x3f)<<10)|(2<<8)|(c&0xff);
}
symbol_t Occult::quadCode(int s,int c,symbol_t c1,symbol_t c2,symbol_t c3,symbol_t c4) {
	return ((((c1&0xfff)<<36)|((c2&0xfff)<<24)|((c3&0xfff)<<12)|(c3&0xfff))<<16)|((s&0x3f)<<10)|(3<<8)|(c&0xff);
}
void Occult::parseCode(symbol_t s,Symbol &r) {
	r.symbol = s;
	r.system = (s>>10)&0x3f;
	r.n = ((s>>8)&3)+1;
	r.concept = s&0xff;
	s >>= 16;
	switch(r.n) {
		case 1:r.c1 = s,r.c2 = 0,r.c3 = 0,r.c4 = 0;break;
		case 2:r.c1 = (s>>24)&0xffffff,r.c2 = s&0xffffff,r.c3 = 0,r.c4 = 0;break;
		case 3:r.c1 = (s>>32)&0xffff,r.c2 = (s>>16)&0xffff,r.c3 = s&0xffff,r.c4 = 0;break;
		case 4:r.c1 = (s>>36)&0xfff,r.c2 = (s>>24)&0xfff,r.c3 = (s>>12)&0xfff,r.c4 = s&0xfff;break;
	}
}

int Occult::elementConv(int elem,int sys) {
	return sys==OCCULT_SYMBOL? elem : elemConv[(sys<<4)+elem];
}
int Occult::elementConvert(int elem,int sys_fr,int sys_to) {
	if(sys_fr==sys_to) return elem;
	int e = elementConv(elem,sys_fr);
	return sys_to==OCCULT_SYMBOL? e : elemConv[(sys_to<<4)+8+e];
}
int Occult::elementToSymbol(int elem,int sys) { return elementConv(elem,sys); }
char Occult::elementChar(int elem,int sys) { return elemConv[elementConv(elem,sys)]; }


enum {
	TXT_MONTHS,
	TXT_SYSTEMS,
	TXT_SYMBOLS,
	TXT_ASTR_QUALITIES,
	TXT_ASTR_ENERGIES,
	TXT_ASTR_PLANETS,
	TXT_ASTR_HOUSES1,
	TXT_ASTR_HOUSES2,
	TXT_ASTR_ASPECTS,
	TXT_ASTR_PATTERNS,
	TXT_ASTR_SHAPINGS,
	TXT_ASTR_FACTORS,
	TXT_ASTR_HSYSTEMS,
	TXT_ASTR_LABELS,
	TXT_ASTR_CONCEPTS1,
	TXT_ASTR_CONCEPTS2,
	TXT_ASTR_CONCEPTS3,
	TXT_ASTR_HEBREW,
	TXT_TAROT_ARCANA,
	TXT_TAROT_MINORS,
	TXT_NUM
};

Occult::Occult() {
	txt = 0;
}

Occult::~Occult() {
	if(txt) {
		int i;
		for(i=0; i<TXT_NUM; i++) delete txt[i];
		free(txt);
		txt = 0;
	}
}

void Occult::load() {
	const char *t[] = {
		"months","systems","symbols",
		"astr.qualities","astr.energies","astr.planets","astr.houses1","astr.houses2",
		"astr.aspects","astr.patterns","astr.shapings","astr.factors","astr.hsystems","astr.labels",
		"astr.concepts1","astr.concepts2","astr.concepts3",
		"hebrew",
		"tarot.arcana","tarot.minors",
	};
	int i;
	if(!txt) {
		txt = (aVector **)malloc(sizeof(aVector *)*TXT_NUM);
		memset(txt,0,sizeof(aVector *)*TXT_NUM);
	}
	for(i=0; i<TXT_NUM; i++) {
		if(txt[i]) { delete txt[i];txt[i] = 0; }
		if(t[i]) {
			txt[i] = new aVector();
			txt[i]->split(app.get(t[i]),",");
		}
	}
}

const char *Occult::month(int m) { return (const char *)(*txt[TXT_MONTHS])[m-1]; }
const char *Occult::system(int s) { return (const char *)(*txt[TXT_SYSTEMS])[s]; }
const char *Occult::symbol(int s) { return (const char *)(*txt[TXT_SYMBOLS])[s]; }

const char *Occult::elementName(int e,int sys) {
	if(sys!=OCCULT_SYMBOL) e = elementConvert(e,sys);
	return (char *)(*txt[TXT_SYMBOLS])[e];
}
const char *Occult::qualityName(int q) { return (const char *)(*txt[TXT_ASTR_QUALITIES])[q]; }
const char *Occult::energyName(int e) { return (const char *)(*txt[TXT_ASTR_ENERGIES])[e]; }
const char *Occult::zodiacName(int z) { return (const char *)(*txt[TXT_SYMBOLS])[z]; }
const char *Occult::planetName(int p) { return (const char *)(*txt[TXT_ASTR_PLANETS])[p]; }
const char *Occult::houseName(int h) { return (const char *)(*txt[TXT_ASTR_HOUSES1])[h]; }
const char *Occult::houseNameShort(int h) { return (const char *)(*txt[TXT_ASTR_HOUSES2])[h]; }
const char *Occult::aspectName(int a) { return (const char *)(*txt[16+ASTRO_ASPECTS])[a]; }
const char *Occult::aspectPatternName(int p) { return (const char *)(*txt[16+ASTRO_PATTERNS])[p]; }
const char *Occult::shapingName(int s) { return (const char *)(*txt[16+ASTRO_SHAPINGS])[s]; }
const char *Occult::factorName(int f) { return (const char *)(*txt[16+ASTRO_FACTORS])[f]; }
const char *Occult::houseSystemName(int h) { return (const char *)(*txt[16+ASTRO_HSYSTEMS])[h]; }
const char *Occult::astroLabel(int l) { return (const char *)(*txt[16+ASTRO_LABELS])[l]; }
const char *Occult::conceptName(int c) { return (const char *)(*txt[16+ASTRO_CONCEPTS])[c]; }
const char *Occult::conceptNamePlur(int c) { return (const char *)(*txt[16+ASTRO_CONCEPTS])[c+ASTRO_CONCEPTS]; }
const char *Occult::conceptNameDefPlur(int c) { return (const char *)(*txt[16+ASTRO_CONCEPTS])[c+2*ASTRO_CONCEPTS]; }

const char *Occult::hebrewLetterName(int h) { return (const char *)(*txt[40+0])[h]; }

const char *Occult::arcanaName(int a) { return (const char *)(*txt[48+0])[a]; }
const char *Occult::minorArcanaName(int m) { return (const char *)(*txt[48+1])[m]; }
